テクニカル Q&A
DV36 - MemAllocatePhysicallyContiguous (1999 年 8 月 23
日)
Q:
私のドライバには物理的に連続したメモリを割り当てる必要があります。MemAllocatePhysicallyContiguous
を呼び出していますが、システムに使用可能なメモリが十分あっても、nil
を返します。どうしたらよいのでしょうか。
A: MemAllocatePhysicallyContiguous
は物理的に連続したメモリを探すのに非常に単純なアルゴリズムを使っています。アルゴリズムの要点は以下の通りです。
on MemAllocatePhysicallyContiguous size
result = NewPtrSys(size)
if result != nil then
if LockMemoryContiguous(result, size) != noErr then
previousResult = result;
result = NewPtrSys(size)
if result != nil then
if LockMemoryContiguous(result, size) != noErr then
DisposePtr(result)
result = nil;
end-if
end-if
DisposePtr(previousResult)
end-if
end-if
return result
end MemAllocatePhysicallyContiguous
注意 :
上記の疑似コードは
MemAllocatePhysicallyContiguous
アルゴリズムを簡単に表したものです。実際のコードは、MemAllocatePhysicallyContiguous
が返すバッファは常にページ境界に揃うことなどのため、もっと複雑です。
|
このアルゴリズムは連続した物理メモリを探す方法として、あまり洗練されたものではありません。具体的には、連続した物理メモリブロックを
2 回探しています。2
回とも失敗すれば、MemAllocatePhysicallyContiguous
はあきらめてエラーを返します。実際には十分なメモリがあって、十分な連続した物理メモリがあっても、MemAllocatePhysicallyContiguous
は見つけられないことがあります。
MemAllocatePhysicallyContiguous が使用する
LockMemoryContiguous
呼び出しの成功を左右する要因はたくさんあります。
要約すると、システムが連続した物理メモリを提供する能力は非常に限られていて、環境的な要因から著しい影響を受けます。
悪い情報はここまでです。幸いにも、この制限は回避することができるので、これからその方法を紹介します。
- 少量のメモリを割り当てる ―
割り当てるメモリの量が少ないほど、メモリが連続している可能性は大きくなります
(極端な話をすると、1
ページ分の連続した物理メモリの割り当ては常に成功します)。巨大な連続した物理メモリブロックを
1
個だけ割り当てようとするのは、最悪の方法です。ドライバを再構築して、より小さいブロックのメモリを多数使用するようにした方がよいでしょう。
- メモリを早期に割り当てる ―
ロードされるタイミングが早いほど、連続した物理メモリを割り当てられる可能性が高くなります。ドライバの中には、オープンされるまでメモリの割り当てを行わず、結果的にその時にはもう連続した物理メモリを取得できないものがあります。これを避けるためには、kDriverIsLoadedUponDiscovery
フラグを指定して、ドライバが起動処理を行っている早い段階でメモリの割り当てを可能にすることです。こうすればドライバがオープンされたときには、割り当て済みのメモリを使用することができるというわけです。
- 後からメモリを割り当てる ―
起動時にメモリの割り当てができないときは、ドライバがオープンされたときや、起動処理の後半でロードされる何らかの他のサービスがドライバにアクセスしてきたときに、割り当てを試みることができます。VM
の改善された LockMemoryContiguous
アルゴリズムが使用できるため、後から割り当てを行うと成功する確率が高まります。
- 分散/収集方式 ― DMA
ハードウェアのほとんどが分散/収集機構 (scatter/gather)
をサポートしています
(分散/収集ハードウェアは、連続した物理メモリの割り当て機構を提供しない
OS
では必須のものです)。デベロッパの多くは分散/収集を敬遠しがちです。効率が落ちること
(ディスクリプタを参照するため PCI
バスサイクルを消費します)、プログラムが難しいことがその理由です。しかし、分散/収集は、MemAllocatePhysicallyContiguous
が nil を返した場合の最終的な解決策です。
以上のテクニックを組み合わせて使えば、最良の結果が得られるでしょう。連続した物理メモリを使うことでカードの性能が大幅に向上するならば、上で説明したテクニックを使って連続した物理メモリを割り当てるべきです。連続した物理メモリ割り当ての試みがすべて失敗した場合、最後の手段として、ハードウェアの分散/収集モードを使用可能にしておくべきでしょう。
-- Quinn "The Eskimo!"
Worldwide Developer Technical Support
テクニカル Q&A | 目次
To contact us, please use the Contact
Us page.
|